/*
    jquery-google-mapper
    A simple jQuery Google Map plugin.
    Built by Dana Woodman.
*/
(function($) {
    
    // The main function.
    $.fn.google_mapper = function(options) {
        var opts = $.extend({}, $.fn.google_mapper.defaults, options);
        return this.each(function() {
            
            var obj = $(this);
            
            // build element specific options
            obj.o = $.meta ? $.extend({}, opts, $this.data()) : opts;
            
            if (GBrowserIsCompatible()) {
                
                // Create a new map object.
                // TODO: Have this be able to handle a jQuery selector, or ideally, a DOM object.
                var map = new GMap2(document.getElementById(obj.o.map_container_id));
                
                if (obj.o.debug) {
                    $.fn.google_mapper.debug('Using Google API version ' + G_API_VERSION);
                    $.fn.google_mapper.debug('There are a total of ' + obj.o.addresses.length + ' address(es).');
                };
                
                // Set map center, if there is only one locaiton.
                if (obj.o.addresses.length == 1) {
                    
                    if (obj.o.debug) { 
                        $.fn.google_mapper.debug('Centering map on lat: "' + obj.o.addresses[0].latlng.lat + '", lng: "' +  obj.o.addresses[0].latlng.lng + '" at default zoom level of ' + obj.o.default_zoom_level);
                    };
                    
                    // Set center if lat-lng pair is supplied.
                    if (obj.o.addresses[0].latlng.lat && obj.o.addresses[0].latlng.lng) {
                        map.setCenter(new GLatLng(obj.o.addresses[0].latlng.lat, obj.o.addresses[0].latlng.lng), obj.o.default_zoom_level);
                    }
                    
                    // Set center if a real address is supplied
                    else {
                        
                        ////////////////////////////////////////////
                        ////////////// GEOCODE HERE ////////////////
                        ////////////////////////////////////////////
                        
                    };
                }
                
                // Set map center, if there is more than one locaiton.
                else {
                    
                    // Grows bounds of box so markers are not on the edge.
                    function growTopBound(map, bounds) {
                        var latlngNorthEast = bounds.getNorthEast();
                        var pointNorthEast = map.fromLatLngToDivPixel(latlngNorthEast);
                        bounds.extend(map.fromDivPixelToLatLng(new GPoint(pointNorthEast.x, pointNorthEast.y - 75)));
                        return bounds;
                    }
                    
                    // Set map center and zoom to world view by default.
                    map.setCenter(new GLatLng(0,0),0);
                    var bounds = new GLatLngBounds();
                    
                    // Extend the bounds for each address till they are each in view.
                    for (i in obj.o.addresses) { 
                        var loc = obj.o.addresses[i].latlng;
                        var latlng = new GLatLng(loc.lat, loc.lng); 
                        bounds.extend(latlng);
                    };
                    
                    // Zoom to bounds of items.
                    map.setZoom(map.getBoundsZoomLevel(bounds));
                    map.setCenter(bounds.getCenter());
                    
                    // Based on the bounds, grow top by a small amount.
                    bounds = growTopBound(map, bounds);
                    
                    // Re-do the zoom.
                    map.setZoom(map.getBoundsZoomLevel(bounds));
                    map.setCenter(bounds.getCenter());

                };
                
                // Add in controls to map.
                if (obj.o.controls['GSmallMapControl'] == true) { map.addControl(new GSmallMapControl()); };
                if (obj.o.controls['GMapTypeControl'] == true) { map.addControl(new GMapTypeControl()); };
                
                // Loop through each address and map it.
                $.each(obj.o.addresses, function() {
                    var add = this;
                    if (obj.o.debug) {
                        $.fn.google_mapper.debug('Address ' + (i+1) + ': lat: "' + add.latlng.lat + '", lng: "' + add.latlng.lng + '"');
                    };
                    
                    // Lat-lng pair was supplied, map it.
                    if (add.latlng.lat && add.latlng.lng) {
                        if (obj.o.debug) {
                            $.fn.google_mapper.debug('Mapping address ' + (i+1));
                        };
                        var point = new GLatLng(add.latlng.lat, add.latlng.lng);
                        var marker = new GMarker(point)
                        map.addOverlay(marker);
                        if (add.info_window_data) {
                            if (obj.o.debug) {
                                $.fn.google_mapper.debug('Address ' + (i+1) + ' has info window data.');
                                $.fn.google_mapper.debug('Adding event listener for address ' + (i+1) + '. Waiting for a "' + obj.o.info_window_event + '" event.');
                            };
                            GEvent.addListener(marker, 'click', function() {
                                if (obj.o.debug) {
                                    $.fn.google_mapper.debug('Address ' + (i+1) + ' has info window data.');
                                };
                                marker.openInfoWindow($.fn.google_mapper.make_info_window(add));
                            });
                        };
                    }
                    
                    // A real address was supplied, geocode and map it.
                    else if (add.real_address) {
                        
                        ////////////////////////////////////////////
                        ////////////// GEOCODE HERE ////////////////
                        ////////////////////////////////////////////
                        
                    }
                    
                    // Neither a lat/lng pair nor a real address were supplied, stop the function.
                    else {
                        // TODO: This functin needs to handle erranous addresses.
                        return false;
                    };
                });
            };
        });
    };
    
    // Constructs the "Info Window" popup that is show when a marker is clicked.
    $.fn.google_mapper.make_info_window = function(address_object) {
        var add = address_object;
        var html = '<div class="map-popup-cont">' + 
            '<h5><a href="' + add.info_window_data.url + '" title="View ' + add.info_window_data.name + '\'s page">' + add.info_window_data.name + '</a></h5>' + 
            '<p style="margin: 5px 0;"><strong>' + add.info_window_data.phone + '</strong></p>' + 
            '<address>' + add.info_window_data.add1 + ' ' + add.info_window_data.add2 + '<br />' + add.info_window_data.city + ', ' + add.info_window_data.state + '<br />' + add.info_window_data.zip +
            '</address>' + 
            '</div>';
        return html;
    };
    
    // A debug function for the google_mapper that checks to see if the console is available for writing. If it's not, default to an alert.
    $.fn.google_mapper.debug = function(string) {
        if (window.console && window.console.log) {
            console.log(string);
        }
        else {
            alert(string);
        };
    };
    
    // The google_mapper defaults, can be overridden in the function itself.
    $.fn.google_mapper.defaults = {
        map_container_id: 'google-map-container',
        controls: {
            GSmallMapControl: true,
            GMapTypeControl: true
        },
        addresses: [
            {
                real_address: null, // The "real" address string.
                latlng: {
                    lat: null, // The latitude of the address as a string.
                    lng: null // The longitude of the address as a string.
                },
                info_window_data: {} // An Object containing the content to display in the "Info Window" popup.
            }
        ],
        default_zoom_level: 14,
        info_window_event: 'click', // Can be any valid jQuery event: 'click', 'hover', etc...
        debug: false
    };
    
})(jQuery);
